-
Notifications
You must be signed in to change notification settings - Fork 42
Fix intermittent ConcurrentModificationException (#92) #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix intermittent ConcurrentModificationException (#92) #93
Conversation
|
@sbraconnier - I see what the change does and I see how it could prevent a concurrent modification exception. Can you link to an issue or discussion or other info about why or when the issue happens? |
|
@jonbartels Sorry I only added the reference in the title. I updated the PR description to link the original issue. |
tonygermano
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this may not actually fix the issue. I can't find any indication that this method would be called concurrently from two threads. The stack traces from the two nextgen issues don't have mirth versions on them, but they indicate that the problem occurs on one of these two lines (the line numbers shifted in mirth 4.4.0):
engine/donkey/src/main/java/com/mirth/connect/donkey/model/message/Message.java
Lines 155 to 156 in 75ca77c
| responseMap.putAll(connectorMessage.getResponseMap()); | |
| channelMap.putAll(connectorMessage.getChannelMap()); |
The map being modified concurrently is the argument to the putAll method. Since this method doesn't update that map, that means there is probably another thread that isn't trying to call this same method, but is instead updating the responseMap or channelMap for the same connectorMessage while this method is trying to read it.
|
Hmm you're right. I think it would be nice to let the synchronized block since the method is building the |
|
My guess without digging into it too much is that a destination queue thread is updating either the responseMap or the connectorMap while the post-processor is trying to build the mergedConnectorMessage. It may be that just setting a couple retry attempts within this method if a ConcurrentModificationException is thrown would take care of it since this is pretty rare, and that wouldn't introduce the performance penalties associated with synchronization between threads. |
0fc1269 to
e7148c5
Compare
e7148c5 to
a76d2da
Compare
…ne#92) Signed-off-by: sbraconnier <simonbraconnier@gmail.com>
…ntegrationEngine#92 Signed-off-by: sbraconnier <simonbraconnier@gmail.com>
a76d2da to
565a76c
Compare
mgaffigan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know the ostrich algorithm is a thing, but this seems like a bad idea to try again. ConcurrentModificationException is a signal we're violating a collection's synchronization contract. It's being "nice" and telling us that so we can find where we went wrong.
If we don't want to synchronize, I'm sure there's a lock-free collection we could use, but I don't imagine that's required.
Why are there multiple threads involved in message processing? I thought each channel thread serially processed messages.
@mgaffigan From reading the issue and the related issues from the nextgen repo, the problem only seems to manifest in high volume channels, and only on rare occasions. I've never seen it before. I have not tried to reproduce it, but I gave my best guess at what is happening in my previous comment. A destination queue thread and post-processor thread are the only scenario I can think of where one might be writing and the other reading the same data structure (one of the message maps, probably the responseMap, in this case) at the same time. I'm open to alternative suggestions if we can pinpoint where the problem actually is. I gave the suggestion as a quick fix to an old problem that was likely to minimally impact people who were not experiencing the problem (most of us.) |
|
@tonygermano From my understanding, the design is:
Of the four assertions above, I'm least confident in the fourth. I would prefer a change which improves error messaging by failing fast when an assumption is broken. |
|
I'd agree here that a minimal reproducible sample should be provided before moving on with this PR. I suggest looking into dedicated load-testing tools. The first one I can think of is |
|
This is obviously a case of something being accessed concurrently that isn't expected to be accessed concurrently. For reference, the description for the HashMap class provides the following information, which I expect applies to how the
|
Fix Intermittent ConcurrentModificationException using getMergedConnectorMessage (#92)